<template>
  <div class="community-page" :style="{ '--sidebar-top': sidebarTop + 'px', '--safe-bottom': safeBottom + 'px', '--viewport-top': viewportTop + 'px', '--gap-x': gapX + 'px', '--sidebar-width': sidebarWidth + 'px' }">
    <div class="app-main">
      <!-- 左侧功能区 -->
      <div class="sidebar-left" ref="sidebarRef">
        <div class="scroll-mask top" v-show="sidebarHasOverflow && sidebarScrollTop > 0"></div>
        <div class="user-card">
          <div class="user-card-header">
            <div class="user-card-avatar">
              <img v-if="userAvatar" :src="userAvatar" :alt="username">
              <div v-else class="user-card-avatar-fallback">{{ (username || '用户').slice(0,1) }}</div>
            </div>
            <div class="user-card-info">
              <div class="user-card-name">{{ username || '用户' }}</div>
              <div class="user-card-level">Lv{{ level }}</div>
            </div>
          </div>
          <div class="user-card-progress">
            <div class="progress-bar">
              <div class="progress-fill" :style="{ width: levelProgress + '%' }"></div>
            </div>
            <div class="progress-text">升级进度 {{ levelProgress }}%</div>
          </div>
        </div>
        <div class="hot-topics">
          <div class="topics-header">
            <h2>热门话题</h2>
          </div>
          <div class="topics-list">
            <div class="topic-item" v-for="tag in hotTags" :key="tag.name" @click="filterByTag(tag.name)" :class="{ active: activeTag === String(tag.name) }">
              #{{ tag.name }}
            </div>
          </div>
        </div>
        
        <!-- 活跃用户榜 -->
        <div class="community-rank">
          <h3>活跃用户榜</h3>
          <div class="rank-list">
            <div class="rank-item" v-for="(u, idx) in activeUsersTop" :key="idx">
              <span class="rank-number" :class="idx === 0 ? 'first' : (idx === 1 ? 'second' : 'third')">{{ idx + 1 }}</span>
              <span class="user">@{{ u.username }}</span>
              <span class="points">{{ u.score }}分</span>
            </div>
            <div class="rank-item" v-if="activeUsersTop.length === 0">
              <span class="rank-number">—</span>
              <span class="user">暂无数据</span>
              <span class="points">--</span>
            </div>
          </div>
          <a href="#" class="more-link" @click.prevent="showRankModal = true">查看更多</a>
        </div>
        
        
        
        <!-- 低碳小贴士 -->
        <div class="carbon-tips">
          <div class="tips-header">
            <h3>低碳小贴士</h3>
          </div>
          <div class="tips-content">
            <div class="tip-item">
              <span class="tip-number">1</span>
              <span class="tip-text">发布动态可获得+5碳积分</span>
            </div>
            <div class="tip-item">
              <span class="tip-number">2</span>
              <span class="tip-text">点赞他人动态可获得+1碳积分</span>
            </div>
            <div class="tip-item">
              <span class="tip-number">3</span>
              <span class="tip-text">评论互动可获得+2碳积分</span>
            </div>
          </div>
        </div>
        
        
        <div class="scroll-mask bottom" v-show="sidebarHasOverflow && sidebarScrollBottom > 0"></div>
      </div>

      <div class="overlay" v-if="showRankModal" @click="showRankModal = false">
        <div class="modal" @click.stop>
          <div class="modal-head">
            <div class="title">活跃用户榜</div>
            <button class="close" @click="showRankModal = false">×</button>
          </div>
          <div class="modal-body">
            <div v-if="loadingRanks" class="loading">正在加载...</div>
            <div v-else class="rank-list">
              <div class="rank-item" v-for="(u, idx) in (activeUsersAll.length ? activeUsersAll : activeUsersTop)" :key="'modal-'+idx">
                <span class="rank-number" :class="idx === 0 ? 'crown' : (idx === 1 ? 'podium' : '')">{{ idx === 0 ? '👑' : (idx === 1 ? '🥈' : (idx === 2 ? '🥉' : idx + 1)) }}</span>
                <span class="user">@{{ u.username }}</span>
                <span class="points">{{ u.score }}分</span>
              </div>
              <div class="rank-item" v-if="(activeUsersAll.length ? activeUsersAll : activeUsersTop).length === 0">
                <span class="rank-number">—</span>
                <span class="user">暂无数据</span>
                <span class="points">--</span>
              </div>
            </div>
            <div class="hint">已显示完整排名</div>
          </div>
        </div>
      </div>
      
      <!-- 右侧瀑布流内容区 -->
      <div class="feed-right" ref="mainContentRef">
        <!-- 发布栏 -->
        <div class="publish-section">
          <div class="publish-input-container">
            <input 
              type="text" 
              placeholder="分享你的低碳生活..." 
              class="publish-input"
              @focus="goToPublish"
            />
            <button class="publish-button" @click="goToPublish">发布</button>
          </div>
        </div>
        
        <!-- 顶部Tab切换栏 -->
        <div class="feed-tabs">
          <button
            class="tab-btn"
            :class="{ active: activeTab === 'recommended' }"
            @click="switchTab('recommended')"
          >推荐</button>
          <button
            class="tab-btn"
            :class="{ active: activeTab === 'latest' }"
            @click="switchTab('latest')"
          >最新</button>
          <button
            class="tab-btn"
            :class="{ active: activeTab === 'nearby' }"
            @click="switchTab('nearby')"
          >附近</button>
        </div>
        
        <!-- 提示信息 -->
        <div v-if="message.text" class="message-toast" :class="message.type">
          {{ message.text }}
        </div>
        
        <!-- 动态列表 -->
        <div class="posts-section">
          <div class="posts-masonry">
            <div class="posts-masonry-column">
              <div class="post-card" v-for="(post, index) in posts.filter((_, i) => i % 2 === 0)" :key="post.post_id" @click="goToPostDetail(post)">
                <!-- 发布者信息 -->
                <div class="post-header">
                  <div class="user-info">
                    <span class="username">{{ post.username || '未知用户' }}</span>
                    <span class="post-time">{{ formatTime(post.created_at) }}</span>
                  </div>
                </div>
                
                <!-- 内容图 -->
                <div class="post-image-container" v-if="post.image_urls && post.image_urls.length > 0">
                  <img :src="post.image_urls[0]" :alt="'动态图片'" class="post-image" />
                </div>
                
                <!-- 内容标题和互动按钮 -->
                <div class="post-card-footer">
                  <h3 class="post-title">{{ post.content || '无内容' }}</h3>
                  <div class="post-actions">
                    <button class="action-btn like-btn" @click.stop="toggleLike(post)" :class="{ liked: post.is_liked, loading: post.isLiking }">
                      <span class="icon">{{ post.is_liked ? '❤️' : '♡' }}</span>
                      <span class="count">{{ post.like_count }}</span>
                    </button>
                    <button class="action-btn comment-btn" @click.stop="goToPostDetail(post)">
                      <span class="icon">
                        <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">
                          <path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm0 14.5c-3.6 0-6.5-2.9-6.5-6.5s2.9-6.5 6.5-6.5 6.5 2.9 6.5 6.5-2.9 6.5-6.5 6.5z"/>
                          <circle cx="5" cy="8" r="1"/>
                          <circle cx="8" cy="8" r="1"/>
                          <circle cx="11" cy="8" r="1"/>
                        </svg>
                      </span>
                      <span class="count">{{ post.comment_count }}</span>
                    </button>
                    <button class="action-btn share-btn" @click.stop>
                      <span class="icon">↗️</span>
                    </button>
                  </div>
                </div>
              </div>
            </div>
            
            <div class="posts-masonry-column">
              <div class="post-card" v-for="(post, index) in posts.filter((_, i) => i % 2 === 1)" :key="post.post_id + '-second'" @click="goToPostDetail(post)">
                <!-- 发布者信息 -->
                <div class="post-header">
                  <div class="user-info">
                    <span class="username">{{ post.username || '未知用户' }}</span>
                    <span class="post-time">{{ formatTime(post.created_at) }}</span>
                  </div>
                </div>
                
                <!-- 内容图 -->
                <div class="post-image-container" v-if="post.image_urls && post.image_urls.length > 0">
                  <img :src="post.image_urls[0]" :alt="'动态图片'" class="post-image" />
                </div>
                
                <!-- 内容标题和互动按钮 -->
                <div class="post-card-footer">
                  <h3 class="post-title">{{ post.content || '无内容' }}</h3>
                  <div class="post-actions">
                    <button class="action-btn like-btn" @click.stop="toggleLike(post)" :class="{ liked: post.is_liked, loading: post.isLiking }">
                      <span class="icon">{{ post.is_liked ? '❤️' : '♡' }}</span>
                      <span class="count">{{ post.like_count }}</span>
                    </button>
                    <button class="action-btn comment-btn" @click.stop="goToPostDetail(post)">
                      <span class="icon">
                        <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">
                          <path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm0 14.5c-3.6 0-6.5-2.9-6.5-6.5s2.9-6.5 6.5-6.5 6.5 2.9 6.5 6.5-2.9 6.5-6.5 6.5z"/>
                          <circle cx="5" cy="8" r="1"/>
                          <circle cx="8" cy="8" r="1"/>
                          <circle cx="11" cy="8" r="1"/>
                        </svg>
                      </span>
                      <span class="count">{{ post.comment_count }}</span>
                    </button>
                    <button class="action-btn share-btn" @click.stop>
                      <span class="icon">↗️</span>
                    </button>
                  </div>
                </div>
              </div>
            </div>
          </div>

          <!-- 当没有帖子时显示提示 -->
          <div v-if="posts.length === 0" class="no-posts">
            <div class="empty-state">
              <div class="empty-icon">💭</div>
              <p class="empty-text">{{ showMyPosts ? '您还没有发布过动态' : '暂无动态，快来发布第一条动态吧！' }}</p>
              <button v-if="!showMyPosts" class="action-btn primary" @click="goToPublish">
                <span class="icon">📝</span>
                <span class="text">发布动态</span>
              </button>
            </div>
          </div>
          <!-- 加载更多与无限滚动 -->
          <div class="load-more-wrapper" v-if="!showMyPosts">
            <button class="load-more-btn" :disabled="isLoadingMore || !hasMore" @click="loadMore">
              <span v-if="isLoadingMore" class="loading-spinner"></span>
              {{ hasMore ? (isLoadingMore ? '加载中...' : '加载更多') : '没有更多内容了' }}
            </button>
            <div ref="infiniteSentinel" class="infinite-sentinel"></div>
          </div>
        </div>
        <div class="scroll-mask top" v-show="contentHasOverflow && contentScrollTop > 0"></div>
        <div class="scroll-mask bottom" v-show="contentHasOverflow && contentScrollBottom > 0"></div>
      </div>
      
  </div>
    
    <transition name="modal-fade">
      <div v-if="showPublishModal" class="modal-overlay" @click.self="closePublishModal" role="dialog" aria-modal="true" aria-labelledby="publishModalTitle">
        <div class="modal-card">
          <div class="modal-header">
            <h3 id="publishModalTitle" class="modal-title">发布新动态</h3>
            <button class="modal-close" @click="closePublishModal" aria-label="关闭">×</button>
          </div>
          <div class="modal-body">
            <Publish asModal @published="onPublished" @close="closePublishModal" />
          </div>
        </div>
      </div>
    </transition>

    <!-- 动态详情弹窗 -->
    <div v-if="showPostModal" class="detail-modal-overlay" @click.self="closePostModal">
      <button class="detail-close-floating" @click="closePostModal">← 返回</button>
      <PostDetailModal :postId="selectedPostId" @close="closePostModal" />
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, computed, inject, watch } from 'vue'
import { useRouter } from 'vue-router'
import EmojiTextarea from '../components/EmojiTextarea.vue'
import Publish from './Publish.vue'
import PostDetailModal from '@/components/PostDetailModal.vue'
import { getPosts, getUserPosts, deletePost, likePost, unlikePost, getComments, createComment, deleteComment, getTags } from '../api/community'
import { getUserLeaderboard } from '@/api/user'
import request from '../utls/require'

const router = useRouter()

// 响应式数据
const posts = ref<any[]>([])
const showMyPosts = ref(false)
const allPostsCount = ref(0)
const myPostsCount = ref(0)
const locationLabels = ref<Record<string, string>>({})
const hotTags = ref<{name: string, post_count: number}[]>([])
const username = ref('用户')
const userAvatar = ref('')
const userPoints = ref(0)
const level = ref(1)
const levelProgress = ref(0)
const activeUsersTop = ref<{username: string, score: number}[]>([])
const activeUsersAll = ref<{username: string, score: number}[]>([])
const loadingRanks = ref(false)
const showRankModal = ref(false)
const message = ref({ text: '', type: 'success' })
const showPublishModal = ref(false)
const showPostModal = ref(false)
const selectedPostId = ref<number>(0)
 

// 加载活跃用户榜（周榜前3）
async function loadActiveUsersTop() {
  try {
    const resp: any = await getUserLeaderboard(3)
    const items = (resp?.data?.items || resp?.data || []) as any[]
    const mapped = items.map((x: any) => ({
      username: x.username || '用户',
      score: Number(x.points ?? x.total_points ?? x.total_score ?? 0)
    }))
    activeUsersTop.value = mapped.sort((a: any, b: any) => b.score - a.score).slice(0, 3)
  } catch (e) {
    console.error('获取活跃用户榜失败:', e)
    activeUsersTop.value = []
  }
}

async function loadActiveUsersAll(limit = 50) {
  try {
    loadingRanks.value = true
    const resp: any = await getUserLeaderboard(limit)
    const items = (resp?.data?.items || resp?.data || []) as any[]
    const mapped = items.map((x: any) => ({
      username: x.username || '用户',
      score: Number(x.points ?? x.total_points ?? x.total_score ?? 0)
    }))
    activeUsersAll.value = mapped.sort((a: any, b: any) => b.score - a.score)
  } catch (e) {
    console.error('获取完整活跃用户榜失败:', e)
    activeUsersAll.value = []
  } finally {
    loadingRanks.value = false
  }
}
const activeTab = ref<'recommended' | 'latest' | 'nearby'>('recommended')
const activeTag = ref<string | null>(null)
const page = ref(1)
const initialPageLimit = 10
const loadMoreLimit = 5
const getPageLimit = () => (page.value === 1 ? initialPageLimit : loadMoreLimit)
const isLoadingMore = ref(false)
const hasMore = ref(true)
const infiniteSentinel = ref<HTMLElement | null>(null)
const reverseServiceDown = ref(false)
let observer: IntersectionObserver | null = null
const mainContentRef = ref<HTMLElement | null>(null)
const sidebarRef = ref<HTMLElement | null>(null)
const sidebarTop = ref(100)
const safeBottom = ref(50)
const viewportTop = ref(20)
const gapX = ref(30)
const sidebarWidth = ref(320)
const contentHasOverflow = ref(false)
const sidebarHasOverflow = ref(false)
const contentScrollTop = ref(0)
const contentScrollBottom = ref(0)
const sidebarScrollTop = ref(0)
const sidebarScrollBottom = ref(0)

const triggerPointsToast = inject<(delta: number) => void>('triggerPointsToast')

// 跳转到动态详情页
const goToPostDetail = (post: any) => {
  if (post && post.post_id) {
    router.push(`/post/${post.post_id}`)
  }
}

const getLocationKey = (post: any): string | null => {
  if (post?.post_id !== undefined && post?.post_id !== null) return String(post.post_id)
  const lat = post?.lat ?? post?.latitude
  const lng = post?.lng ?? post?.longitude
  if (typeof lat === 'number' && typeof lng === 'number') return `${lat},${lng}`
  return null
}

const getPreferredLocation = (post: any): string => {
  const key = getLocationKey(post)
  const cached = key ? locationLabels.value[key] : ''
  return cached || getLocationLabel(post) || '未知位置'
}

// 方法
const currentOrder = () => {
  if (activeTab.value === 'recommended') return 'recommended'
  if (activeTab.value === 'latest') return ''
  if (activeTab.value === 'nearby') return 'nearby'
  return ''
}

const fetchPosts = async (merge = false) => {
  try {
    const pageSize = getPageLimit()
    const params: any = { page: page.value, limit: pageSize, page_size: pageSize }
    const order = currentOrder()
    if (order) params.order = order
    const response = await getPosts(params)
    let list: any[] = response?.data?.posts || []
    // 客户端兜底：当后端未分页或返回过多时，限制到当前页大小
    if (!merge) {
      list = list.slice(0, pageSize)
      posts.value = list
    } else {
      // 合并时按limit截断当页数据
      const pageChunk = list.slice(0, pageSize)
      posts.value = posts.value.concat(pageChunk)
    }
    const apiTotal = response?.data?.total
    hasMore.value = typeof apiTotal === 'number' ? (posts.value.length < apiTotal) : (list.length === getPageLimit())
    allPostsCount.value = typeof apiTotal === 'number' ? apiTotal : posts.value.length
    resolveLocationsForPosts(posts.value)
  } catch (error) {
    console.error('获取帖子列表失败:', error)
    posts.value = []
    hasMore.value = false
  }
}

const loadHotTags = async () => {
  try {
    const response = await getTags()
    const tags = response?.data?.tags || []
    hotTags.value = Array.isArray(tags) ? tags.slice(0, 5) : []
  } catch (error) {
    console.error('获取热门标签失败:', error)
  }
}

const goToPublish = () => {
  showPublishModal.value = true
}

const closePublishModal = () => {
  showPublishModal.value = false
}

const onPublished = () => {
  showPublishModal.value = false
  showMessage('发布成功', 'success')
  page.value = 1
  fetchPosts(false)
}

const closePostModal = () => {
  showPostModal.value = false
}

const onKeyDown = (e: KeyboardEvent) => {
  if (e.key === 'Escape' && showPublishModal.value) {
    e.preventDefault()
    closePublishModal()
  }
}

const showAllPosts = () => {
  showMyPosts.value = false
  page.value = 1
  fetchPosts(false)
  activeTag.value = null
}

const showMyPostsPage = async () => {
  showMyPosts.value = true
  // 获取当前用户的帖子
  try {
    const response = await getUserPosts()
    posts.value = response.data.posts || []
    myPostsCount.value = response.data.total || 0
    resolveLocationsForPosts(posts.value)
  } catch (error) {
    console.error('获取我的帖子列表失败:', error)
    posts.value = []
  }
}

const toggleLike = async (post: any) => {
  // 防止重复点击
  if (post.isLiking) return;
  
  try {
    // 设置加载状态
    post.isLiking = true;
    
    // 先更新UI以提供即时反馈
    const originalLiked = post.is_liked;
    const originalCount = post.like_count;
    
    if (post.is_liked) {
      // 准备取消点赞
      post.like_count = Math.max(0, post.like_count - 1); // 确保点赞数不为负
      post.is_liked = false;
      
      // 调用取消点赞接口
      await unlikePost(post.post_id);
      showMessage('取消点赞成功', 'success');
      
      // 如果显示了点赞用户列表，更新列表
      if (post.showLikes && post.likes && Array.isArray(post.likes)) {
        // 这里可以根据实际需求更新点赞用户列表
        // 例如，移除当前用户的点赞信息
      }
    } else {
      // 准备点赞
      post.like_count++;
      post.is_liked = true;
      
      await likePost(post.post_id);
      showMessage('点赞成功', 'success');
      triggerPointsToast?.(1)
    }
  } catch (error) {
    console.error('点赞操作失败:', error);
    // 发生错误时恢复原始状态
    post.is_liked = !post.is_liked;
    post.like_count = post.is_liked ? post.like_count + 1 : Math.max(0, post.like_count - 1);
    showMessage('操作失败，请稍后重试', 'error');
  } finally {
    // 无论成功失败，都清除加载状态
    setTimeout(() => {
      post.isLiking = false;
    }, 300); // 给用户一点时间看到UI变化
  }
}

const toggleComments = async (post: any) => {
  post.showComments = !post.showComments
  
  // 如果是打开评论区域，则加载评论列表
  if (post.showComments && !post.comments) {
    // 添加加载状态
    post.isLoadingComments = true
    try {
      const response = await getComments(post.post_id)
      post.comments = response.data.comments || []
      // 如果没有评论，显示提示
      if (post.comments.length === 0) {
        post.noCommentsMessage = '暂无评论，快来抢沙发吧！'
      }
    } catch (error) {
      console.error('获取评论列表失败:', error)
      post.comments = []
      post.loadingCommentsError = '加载评论失败，请稍后重试'
    } finally {
      // 无论成功失败，都清除加载状态
      post.isLoadingComments = false
    }
  }
}

// 简单的消息提示函数
const showMessage = (msg: string, type: 'success' | 'error' = 'success') => {
  // 设置消息内容和类型
  message.value = { text: msg, type }
  
  // 3秒后自动清除消息
  setTimeout(() => {
    message.value = { text: '', type: 'success' }
  }, 3000)
}

const submitComment = async (post: any) => {
  // 输入验证
  const commentContent = post.newComment?.trim()
  if (!commentContent) {
    showMessage('请输入评论内容', 'error')
    return
  }
  
  // 限制评论长度
  if (commentContent.length < 2) {
    showMessage('评论内容至少需要2个字符', 'error')
    return
  }
  
  // 防止重复提交
  if (post.isSubmittingComment) return
  
  // 添加加载状态
  const originalContent = post.newComment
  post.isSubmittingComment = true
  
  try {
    const response = await createComment(post.post_id, {
      content: commentContent
    })
    
    // 检查响应是否成功
    if (response && response.data) {
      // 添加新评论到列表开头，最新的评论显示在前面
      if (!post.comments) {
        post.comments = []
      }
      
      // 确保新评论包含必要的字段，增强健壮性
      const newComment = {
        ...response.data,
        comment_id: response.data.comment_id || Date.now(),
        username: response.data.username || '我',
        created_at: response.data.created_at || new Date().toISOString(),
        content: response.data.content || commentContent
      }
      
      post.comments.unshift(newComment)
      
      // 清空输入框
      post.newComment = ''
      
      // 增加评论计数
      post.comment_count = (post.comment_count || 0) + 1
      
      // 清除无评论提示
      if (post.noCommentsMessage) {
        delete post.noCommentsMessage
      }
      
      showMessage('评论发表成功', 'success')
      triggerPointsToast?.(2)
    } else {
      showMessage('评论失败，服务器返回异常', 'error')
    }
  } catch (error: any) {
    console.error('发表评论失败:', error)
    // 根据错误类型显示更具体的提示
    const errorMessage = error.response?.data?.message || '评论失败，请稍后重试'
    showMessage(errorMessage, 'error')
    // 恢复输入框内容
    post.newComment = originalContent
  } finally {
    post.isSubmittingComment = false
  }
}

const deletePostItem = async (post: any) => {
  const ok = confirm('确定要删除这条动态吗？')
  if (!ok) return
  try {
    await deletePost(post.post_id)
    fetchPosts(false)
  } catch (error) {
    console.error('删除帖子失败:', error)
    showMessage('删除帖子失败，请稍后重试', 'error')
  }
}

const deleteCommentItem = async (post: any, comment: any) => {
  const ok = confirm('确定要删除这条评论吗？')
  if (!ok) return
  try {
    await deleteComment(comment.comment_id)
    if (post.comments) {
      const index = post.comments.findIndex((c: any) => c.comment_id === comment.comment_id)
      if (index > -1) {
        post.comments.splice(index, 1)
      }
    }
    post.comment_count -= 1
  } catch (error) {
    console.error('删除评论失败:', error)
    showMessage('删除评论失败，请稍后重试', 'error')
  }
}

const previewImage = (image: string) => {
  // 图片预览功能
  console.log('预览图片:', image)
}

const formatTime = (time: string) => {
  // 时间格式化
  const date = new Date(time)
  return date.toLocaleString()
}

const getLocationLabel = (post: any): string => {
  // 按优先级检查位置字段
  if (post?.city && post?.province) {
    return `${post.province} ${post.city}`
  }
  if (post?.province) {
    return post.province
  }
  if (post?.city) {
    return post.city
  }
  return (
    post?.location_name ||
    post?.location ||
    post?.address ||
    ''
  )
}

const formatAddress = (data: any): string => {
  const ad = data?.ad_info || {}
  const fa = data?.formatted_addresses || {}
  const addr = data?.address || ''
  const parts = [ad.province, ad.city, ad.district].filter(Boolean)
  const tail = fa.recommend || fa.rough || addr || ''
  return parts.length ? `${parts.join(' ')} ${tail}`.trim() : tail
}

const formatLatLng = (lat: number, lng: number): string => {
  const la = Number(lat).toFixed(4)
  const ln = Number(lng).toFixed(4)
  return `${la}, ${ln}`
}

const resolveLocation = async (post: any) => {
  const key = String(post.post_id || `${post.lat},${post.lng}`)
  if (locationLabels.value[key]) return
  const text = post?.location_name || post?.location || post?.city || post?.address
  if (text) {
    locationLabels.value[key] = text
    return
  }
  const lat = post?.lat ?? post?.latitude
  const lng = post?.lng ?? post?.longitude
  if (typeof lat === 'number' && typeof lng === 'number') {
    try {
      if (reverseServiceDown.value) {
        locationLabels.value[key] = formatLatLng(lat, lng)
        return
      }
      const resp: any = await request({
        url: '/xiangsu/location/reverse/',
        method: 'get',
        params: { lat, lng }
      })
      if (resp?.success && resp?.data) {
        locationLabels.value[key] = formatAddress(resp.data)
        return
      }
    } catch (e) {
      reverseServiceDown.value = true
    }
    // 回退到经纬度文本，避免显示“未知位置”
    locationLabels.value[key] = formatLatLng(lat, lng)
  }
}

const resolveLocationsForPosts = (list: any[]) => {
  list.forEach(p => resolveLocation(p))
}

// 根据标签筛选动态
const filterByTag = async (tagName: string) => {
  const tagKey = String(tagName)
  // 二次点击取消选择：当再次点击同一标签时取消筛选，回到全部动态
  if (activeTag.value === tagKey) {
    activeTag.value = null
    showAllPosts()
    return
  }
  try {
    page.value = 1
    const pageSize = initialPageLimit
    const params: any = { tag: tagKey, page: 1, limit: pageSize, page_size: pageSize }
    const response = await getPosts(params)
    let list: any[] = response?.data?.posts || []
    posts.value = list.slice(0, pageSize)
    const apiTotal = response?.data?.total
    allPostsCount.value = typeof apiTotal === 'number' ? apiTotal : posts.value.length
    hasMore.value = typeof apiTotal === 'number' ? (posts.value.length < apiTotal) : (list.length === pageSize)
    resolveLocationsForPosts(posts.value)
    activeTag.value = tagKey
  } catch (error) {
    console.error('根据标签筛选动态失败:', error)
    posts.value = []
    hasMore.value = false
  }
}

onMounted(() => {
  window.addEventListener('keydown', onKeyDown)
  // 组件挂载时获取数据
  fetchPosts(false)
  loadHotTags()
  loadActiveUsersTop()

  const savedUsername = localStorage.getItem('username') || sessionStorage.getItem('username')
  const savedAvatar = localStorage.getItem('userAvatar') || sessionStorage.getItem('userAvatar')
  const savedPoints = localStorage.getItem('userPoints') || sessionStorage.getItem('userPoints')
  if (savedUsername) username.value = savedUsername
  if (savedAvatar) userAvatar.value = savedAvatar
  if (savedPoints) {
    userPoints.value = parseInt(savedPoints)
    level.value = Math.max(1, Math.floor(userPoints.value / 100) + 1)
    levelProgress.value = Math.min(100, Math.round((userPoints.value % 100)))
  }

  setTimeout(() => {
    // 计算左右悬浮区与中间内容顶部对齐的偏移量（在未滑动时对齐）
    if (mainContentRef.value) {
      const rect = mainContentRef.value.getBoundingClientRect()
      sidebarTop.value = Math.max(0, Math.round(rect.top))
      updateScrollStates()
    }
    bindScrollHandlers()

    if (infiniteSentinel.value) {
      observer = new IntersectionObserver(entries => {
        entries.forEach(entry => {
          if (entry.isIntersecting && hasMore.value && !isLoadingMore.value && !showMyPosts.value) {
            loadMore()
          }
        })
      }, { rootMargin: '200px' })
      observer.observe(infiniteSentinel.value)
    }
  }, 0)
})

watch(showRankModal, (v) => { if (v) loadActiveUsersAll(50) })

onUnmounted(() => {
  window.removeEventListener('keydown', onKeyDown)
  unbindScrollHandlers()
})

const switchTab = (tab: 'recommended' | 'latest' | 'nearby') => {
  activeTab.value = tab
  showMyPosts.value = false
  page.value = 1
  fetchPosts(false)
}

function updateScrollStates() {
  const contentEl = mainContentRef.value
  const sidebarEl = sidebarRef.value
  if (contentEl) {
    const sh = contentEl.scrollHeight
    const ch = contentEl.clientHeight
    contentHasOverflow.value = sh > ch
    contentScrollTop.value = contentEl.scrollTop
    contentScrollBottom.value = Math.max(0, sh - ch - contentEl.scrollTop)
  }
  if (sidebarEl) {
    const sh = sidebarEl.scrollHeight
    const ch = sidebarEl.clientHeight
    sidebarHasOverflow.value = sh > ch
    sidebarScrollTop.value = sidebarEl.scrollTop
    sidebarScrollBottom.value = Math.max(0, sh - ch - sidebarEl.scrollTop)
  }
}

function onWheel(e: WheelEvent) {
  const target = e.currentTarget as HTMLElement
  if (!target) return
  const delta = e.deltaY
  target.style.willChange = 'transform'
  target.scrollTop += delta
  updateScrollStates()
}

function onTouchStart(e: TouchEvent) {
  const target = e.currentTarget as HTMLElement
  if (!target) return
  ;(target as any).__touchStartY = e.touches[0]?.clientY || 0
}

function onTouchMove(e: TouchEvent) {
  const target = e.currentTarget as HTMLElement
  if (!target) return
  const startY = (target as any).__touchStartY || 0
  const currentY = e.touches[0]?.clientY || 0
  const delta = startY - currentY
  target.scrollTop += delta
  ;(target as any).__touchStartY = currentY
  updateScrollStates()
}

function bindScrollHandlers() {
  const c = mainContentRef.value
  const s = sidebarRef.value
  if (c) {
    c.addEventListener('wheel', onWheel, { passive: true })
    c.addEventListener('touchstart', onTouchStart, { passive: true })
    c.addEventListener('touchmove', onTouchMove, { passive: true })
    c.addEventListener('scroll', updateScrollStates, { passive: true })
  }
  if (s) {
    s.addEventListener('wheel', onWheel, { passive: true })
    s.addEventListener('touchstart', onTouchStart, { passive: true })
    s.addEventListener('touchmove', onTouchMove, { passive: true })
    s.addEventListener('scroll', updateScrollStates, { passive: true })
  }
}

function unbindScrollHandlers() {
  const c = mainContentRef.value
  const s = sidebarRef.value
  if (c) {
    c.removeEventListener('wheel', onWheel)
    c.removeEventListener('touchstart', onTouchStart)
    c.removeEventListener('touchmove', onTouchMove)
    c.removeEventListener('scroll', updateScrollStates)
  }
  if (s) {
    s.removeEventListener('wheel', onWheel)
    s.removeEventListener('touchstart', onTouchStart)
    s.removeEventListener('touchmove', onTouchMove)
    s.removeEventListener('scroll', updateScrollStates)
  }
}

const loadMore = async () => {
  if (isLoadingMore.value || !hasMore.value) return
  isLoadingMore.value = true
  try {
    page.value += 1
    await fetchPosts(true)
  } finally {
    isLoadingMore.value = false
  }
}
</script>

<style scoped>
/* 视觉风格 */
.community-page {
  padding: 24px;
  max-width: 1280px;
  margin: 0 auto;
  background: transparent;
  color: #2C3E50;
  padding-bottom: var(--safe-bottom, 80px);
  scroll-behavior: smooth;
}

.app-main {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: var(--gap-x, 30px);
  min-height: calc(100vh - var(--viewport-top, 20px) - var(--safe-bottom, 50px));
}

.feed-right {
  position: absolute;
  top: var(--viewport-top, 20px);
  right: 0;
  left: calc(var(--sidebar-width, 320px) + var(--gap-x, 30px));
  z-index: 1;
  max-height: calc(100vh - var(--viewport-top, 20px) - var(--safe-bottom, 50px));
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  will-change: transform;
  transform: translateZ(0);
  scrollbar-gutter: stable both-edges;
  padding-right: 6px;
}

.sidebar-left {
  display: flex;
  flex-direction: column;
  gap: 24px;
  position: sticky;
  top: var(--viewport-top, 20px);
  align-self: flex-start;
  z-index: 2;
  width: var(--sidebar-width, 320px);
  flex: 0 0 var(--sidebar-width, 320px);
  max-height: calc(100vh - var(--viewport-top, 20px) - var(--safe-bottom, 50px));
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  will-change: transform;
  transform: translateZ(0);
}
.feed-right.has-overflow {}

.sidebar-left,
.feed-right {
  scrollbar-width: thin;
  scrollbar-color: rgba(0,0,0,0.2) transparent;
}
.sidebar-left::-webkit-scrollbar,
.feed-right::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}
.sidebar-left::-webkit-scrollbar-track,
.feed-right::-webkit-scrollbar-track {
  background: transparent;
}
.sidebar-left::-webkit-scrollbar-thumb,
.feed-right::-webkit-scrollbar-thumb {
  background: rgba(0,0,0,0.18);
  border-radius: 999px;
  border: 2px solid transparent;
  background-clip: padding-box;
}
.sidebar-left:hover::-webkit-scrollbar-thumb,
.feed-right:hover::-webkit-scrollbar-thumb {
  background: rgba(0,0,0,0.3);
}
.sidebar-left::-webkit-scrollbar-corner,
.feed-right::-webkit-scrollbar-corner { background: transparent; }

.card-base {
  background: #FFFFFF;
  border-radius: 16px;
  padding: 24px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.04);
  border: none;
}

.user-card { padding: 24px; }

.user-card-header {
  display: flex;
  align-items: center;
  gap: 12px;
}

.user-card-avatar {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  overflow: hidden;
  background: #F0F3F2;
  display: flex;
  align-items: center;
  justify-content: center;
}

.user-card-avatar img { width: 100%; height: 100%; object-fit: cover; }

.user-card-avatar-fallback { color: #333; font-weight: 700; font-size: 18px; }

.user-card-info { display: flex; flex-direction: column; }
.user-card-name { color: #2C3E50; font-weight: 700; }
.user-card-level { color: #4E8E68; font-weight: 600; }

.user-card-progress { margin-top: 12px; }
.progress-bar { height: 8px; background: #E8EBEE; border-radius: 999px; overflow: hidden; }
.progress-fill { height: 100%; background: #4E8E68; border-radius: 999px; transition: width 0.3s ease; }
.progress-text { margin-top: 8px; color: #86909C; font-size: 12px; }

.publish-btn-large {
  width: 100%;
  padding: 14px 18px;
  background: linear-gradient(45deg, #4E8E68, #3D9E75);
  color: #FFFFFF;
  border: none;
  border-radius: 999px;
  font-size: 1rem;
  font-weight: 600;
  cursor: pointer;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
}
.publish-icon { margin-right: 8px; }

/* 移除垂直导航样式 */

.publish-module, .view-navigation, .hot-topics,
.carbon-tips, .community-rank {
  background: #FFFFFF;
  border-radius: 16px;
  padding: 24px;
  box-shadow: 0 4px 20px rgba(0,0,0,0.04);
  border: none;
}

.scroll-mask {
  position: sticky;
  left: 0;
  right: 0;
  height: 24px;
  z-index: 3;
  pointer-events: none;
}
.scroll-mask.top {
  top: 0;
  background: linear-gradient(to bottom, rgba(0,0,0,0.08), rgba(0,0,0,0));
}
.scroll-mask.bottom {
  bottom: 0;
  background: linear-gradient(to top, rgba(0,0,0,0.08), rgba(0,0,0,0));
}

.publish-header, .nav-header, .topics-header,
.tips-header {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 15px;
}

.publish-header h2, .nav-header h2, .topics-header h2,
.tips-header h3 { margin: 0; color: #2C3E50; font-weight: 700; }

.publish-btn {
  width: 100%;
  padding: 14px 18px;
  background: #73A986;
  color: #FFFFFF;
  border: none;
  border-radius: 999px;
  font-size: 1rem;
  font-weight: 600;
  cursor: pointer;
  transition: transform 0.2s, box-shadow 0.2s;
}

.publish-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 24px rgba(115,169,134,0.25);
}

.nav-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.nav-item {
  padding: 12px 16px;
  border-radius: 8px;
  cursor: pointer;
  transition: background-color 0.2s;
  display: flex;
  justify-content: space-between;
  align-items: center;
  border: none;
}

.nav-item:hover {
  background-color: #F0F3F2;
}

.nav-item.active {
  background-color: #73A986;
  color: #FFFFFF;
  font-weight: 500;
}

.main-content {
  background: #FFFFFF;
  border-radius: 16px;
  padding: 24px;
  box-shadow: 0 4px 20px rgba(0,0,0,0.05);
  width: var(--feed-width, 840px);
  flex: 0 1 var(--feed-width, 840px);
}

.feed-tabs {
  position: sticky;
  top: 0;
  z-index: 4;
  display: flex;
  gap: 12px;
  padding: 10px 0;
  margin-bottom: 8px;
  background: rgba(255,255,255,0.85);
  backdrop-filter: saturate(180%) blur(8px);
  -webkit-backdrop-filter: saturate(180%) blur(8px);
  border-bottom: 1px solid rgba(0,0,0,0.06);
}

.tab-btn {
  padding: 8px 16px;
  border-radius: 999px;
  border: none;
  background: #E8EBEE;
  color: #2C3E50;
  cursor: pointer;
  font-weight: 600;
}

.tab-btn.active {
  background: #4E8E68;
  color: #FFFFFF;
}

/* 发布栏样式 */
.publish-section {
  margin-bottom: 20px;
}

.publish-input-container {
  display: flex;
  align-items: center;
  border: 1px solid #42b983;
  border-radius: 999px;
  padding: 8px 16px;
  background: #fff;
}

.publish-input {
  flex: 1;
  border: none;
  outline: none;
  padding: 8px 0;
  font-size: 14px;
  background: transparent;
}

.publish-button {
  background: #42b983;
  color: white;
  border: none;
  border-radius: 999px;
  padding: 6px 16px;
  cursor: pointer;
  font-weight: 500;
  transition: background 0.2s;
}

.publish-button:hover {
  background: #3aa876;
}

.posts-section { min-height: 600px; }

/* 瀑布流布局 */
.posts-masonry {
  display: flex;
  gap: 10px;
  justify-content: center;
  margin: 0 auto;
  padding-right: 6px;
}

.posts-masonry-column {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 15px; /* 上下间距15px */
}

.post-card {
  background: #FFFFFF;
  border-radius: 16px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.04);
  padding: 15px;
  border: none;
  width: 100%;
  box-sizing: border-box;
  cursor: pointer; /* 添加指针样式表示可点击 */
}

.post-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.1);
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}

/* 图片容器样式 */
.post-image-container {
  width: 100%;
  margin: 10px 0;
}

.post-image {
  width: 100%;
  height: auto; /* 高度自适应 */
  object-fit: cover; /* 按自身比例显示 */
  border-radius: 8px;
  display: block;
}

/* 内容标题样式 */
.post-title {
  font-size: 16px;
  font-weight: 500;
  color: #2C3E50;
  margin: 10px 0;
  line-height: 1.4;
  display: -webkit-box;
  -webkit-line-clamp: 2; /* 最多显示2行 */
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 内容样式 */
.post-content p {
  margin: 0;
  line-height: 1.6;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .posts-masonry {
    flex-direction: column;
    gap: 10px;
  }
  
  .posts-masonry-column {
    width: 100%;
  }
}

.load-more-wrapper {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 16px 0 8px;
}

.load-more-btn {
  padding: 10px 18px;
  border-radius: 999px;
  border: 1px solid rgba(0,0,0,0.06);
  background: #FFFFFF;
  color: #333;
  cursor: pointer;
}

.load-more-btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.infinite-sentinel { height: 1px; width: 100%; }

.post-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 10px;
}

.user-info {
  display: flex;
  flex-direction: column;
}

.username { 
  margin: 0 0 2px 0; 
  color: #2C3E50; 
  font-size: 0.9rem; 
  font-weight: 600; 
}

.post-time { 
  margin: 0; 
  color: #86909C; 
  font-size: 0.8rem; 
}

.post-content {
  margin-bottom: 15px;
  line-height: 1.6;
}

/* 标签样式 */
.post-tags {
  margin-bottom: 15px;
}

.tag { display: inline-block; padding: 6px 12px; margin-right: 8px; margin-bottom: 8px; background-color: #E8EBEE; color: #4E8E68; border-radius: 999px; font-size: 0.9rem; cursor: pointer; transition: all 0.2s; }

.tag:hover { background-color: #4E8E68; color: #FFFFFF; }

.post-images {
  margin-bottom: 15px;
}

.image-grid { display: grid; gap: 8px; }
.image-grid.single-image { grid-template-columns: 1fr; }
.image-grid.two-image { grid-template-columns: repeat(2, 1fr); }
.image-grid.multi-image { grid-template-columns: repeat(3, 1fr); }
.card-image { position: relative; width: 100%; height: 320px; aspect-ratio: 16 / 9; overflow: hidden; border-radius: 8px; }
.image-grid.single-image .card-image { height: 400px; max-height: 400px; }
.image-grid.two-image .card-image { height: 240px; max-height: 240px; }
.image-grid.multi-image .card-image { height: 200px; max-height: 200px; }
.card-image img { width: 100%; height: 100%; object-fit: cover; cursor: pointer; transition: transform 0.2s; border-radius: 8px; }
.post-content img { display: block; width: 100%; max-height: 400px; object-fit: cover; border-radius: 8px; }

/* 固定六宫格图片布局，保证图片在卡片内显示 */
.six-grid { display: grid; grid-template-columns: repeat(3, 1fr); grid-auto-rows: 160px; gap: 8px; }
.six-slot { position: relative; overflow: hidden; border-radius: 8px; background: #FFFFFF; }
.six-slot img { width: 100%; height: 100%; object-fit: cover; display: block; }

@media (max-width: 768px) {
  .six-grid { grid-auto-rows: 120px; }
}

.card-image img:hover {
  transform: scale(1.05);
}

.post-actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 10px;
}

.action-btn {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 6px 12px;
  border: none;
  background: none;
  color: #6c757d;
  cursor: pointer;
  border-radius: 999px;
  transition: all 0.2s;
  font-size: 0.9rem;
}

.action-btn:hover {
  background: #f0f0f0;
  color: #4E8E68;
}

.action-btn.liked {
  color: #e74c3c;
}

.action-btn.loading {
  opacity: 0.6;
  pointer-events: none;
}

.action-btn .count {
  font-size: 0.85rem;
}

.action-btn .icon {
  font-size: 16px;
}

.action-btn.like-btn {
  color: #6c757d;
}

.action-btn.like-btn.liked {
  color: #e74c3c;
}

@keyframes pulse {
  0% {
    opacity: 0.7;
  }
  50% {
    opacity: 0.4;
  }
  100% {
    opacity: 0.7;
  }
}

/* 点赞动画效果 */
.action-btn.like-btn:active {
  transform: scale(1.1);
  transition: transform 0.1s;
}

/* 添加删除评论按钮样式 */
/* 保留上方的删除评论与评论头样式，移除重复定义 */

.delete-btn {
  padding: 6px 10px;
  border: none;
  background: #ff6b6b;
  color: white;
  border-radius: 6px;
  cursor: pointer;
  transition: background-color 0.2s;
}

.delete-btn:hover {
  background: #ff5252;
}

.comments-section {
  border-top: 1px solid #eee;
  padding-top: 15px;
}

/* 评论加载状态 */
.comments-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 20px;
  color: #6c757d;
}

/* 加载动画样式 */
.loading-spinner {
  width: 20px;
  height: 20px;
  border: 2px solid #f3f3f3;
  border-top: 2px solid #42b983;
  border-radius: 50%;
  animation: spin 1s linear infinite;
  display: inline-block;
  margin-right: 6px;
}

.loading-spinner.small {
  width: 14px;
  height: 14px;
  border-width: 1.5px;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

/* 评论加载错误状态 */
.comments-error {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 20px;
  color: #e74c3c;
  flex-wrap: wrap;
}

.error-icon {
  font-size: 1.2rem;
}

.retry-btn {
  padding: 6px 14px;
  background: #73A986;
  color: #FFFFFF;
  border: none;
  border-radius: 12px;
  cursor: pointer;
  font-size: 0.9rem;
  transition: background-color 0.2s;
}

.retry-btn:hover {
  background: #5E8F73;
}

.comment-item {
  padding: 10px 0;
  border-bottom: 1px solid #f5f5f5;
}

.comment-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.comment-author {
  font-weight: 500;
  color: #2c3e50;
}

.comment-time {
  color: #6c757d;
  font-size: 0.85rem;
}

.comment-content {
  color: #495057;
  line-height: 1.5;
}

.comment-form {
  display: flex;
  gap: 10px;
  margin-top: 15px;
}

.comment-input-wrapper {
  width: 100%;
  border-radius: 8px;
  overflow: hidden;
}

.comment-input-wrapper textarea {
  width: 100%;
  border: 1px solid #ddd;
  border-radius: 8px;
  padding: 10px;
  font-size: 14px;
  resize: vertical;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
  font-family: inherit;
}

.comment-input-wrapper textarea:focus {
  outline: none;
  border-color: #42b983;
  box-shadow: 0 0 0 3px rgba(66, 185, 131, 0.1);
}

.comment-input-wrapper textarea::placeholder {
  color: #999;
  font-size: 13px;
}

.comment-input {
  flex: 1;
  padding: 8px 12px;
  border: 1px solid #ddd;
  border-radius: 6px;
  resize: none;
  min-height: 36px;
}

.submit-comment-btn {
  padding: 8px 16px;
  background: #42b983;
  color: white;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.2s ease;
  min-width: 80px;
}

.submit-comment-btn:hover:not(:disabled) {
  background: #3aa876;
  transform: translateY(-1px);
  box-shadow: 0 2px 6px rgba(66, 185, 131, 0.3);
}

.submit-comment-btn:active:not(:disabled) {
  transform: translateY(0);
}

.submit-comment-btn:disabled {
  background: #cccccc;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
  opacity: 0.7;
}

.no-posts {
  text-align: center;
  padding: 60px 20px;
}

.empty-state {
  color: #6c757d;
}

.empty-icon {
  font-size: 3rem;
  margin-bottom: 15px;
}

.empty-text {
  margin: 0 0 20px 0;
  font-size: 1.1rem;
}

.tip-item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin-bottom: 12px;
}

.tip-number {
  font-weight: bold;
  width: 48px;
  font-size: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-right: 12px;
  color: #42b983;
}

.artistic-number {
  font-weight: bold;
  width: 48px;
  font-size: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-right: 12px;
}

.artistic-number.one {
  color: #d4af37;
}

.artistic-number.two {
  color: #b0b0b0;
}

.artistic-number.three {
  color: #cd7f32;
}

.tip-text {
  color: #6c757d;
  font-size: 0.9rem;
  line-height: 1.4;
}

.more-link {
  color: #42b983;
  text-decoration: none;
  font-size: 0.9rem;
  font-weight: 500;
}

.overlay {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}
.modal {
  background: #fff;
  border-radius: 16px;
  box-shadow: 0 10px 30px rgba(0,0,0,0.2);
  width: 90%;
  max-width: 560px;
  padding: 20px;
}
.modal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.title { font-weight: 700; color: #2C3E50; }
.close { border: none; background: transparent; font-size: 20px; cursor: pointer; color: #86909C; }
.modal-body { max-height: 60vh; overflow-y: auto; }
.hint { margin-top: 10px; color: #86909C; font-size: 12px; text-align: center; }
.loading { color: #86909C; font-size: 14px; text-align: center; padding: 20px 0; }

.community-rank h3 {
  margin: 0 0 15px 0;
  color: #333;
  padding-bottom: 10px;
}

.rank-list {
  display: flex;
  flex-direction: column;
  gap: 15px;
}

.rank-item {
  display: flex;
  justify-content: space-between;
  padding: 10px 0;
  border-bottom: 1px solid #eee;
  font-size: 0.9rem;
}

.rank-item:last-child {
  border-bottom: none;
}

.rank-number {
  font-weight: bold;
  width: 48px;
  font-size: 14px;
}
.rank-number.first { color: #d4af37; }
.rank-number.second { color: #b0b0b0; }
.rank-number.third { color: #cd7f32; }

.user { color: #73A986; font-weight: 500; }

.points {
  color: #42b983;
}

 

/* 热门话题样式 */
.topics-list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.topic-item {
  padding: 6px 12px;
  background: #E8EBEE;
  color: #2C3E50;
  border-radius: 999px;
  cursor: pointer;
  transition: all 0.2s;
}
.topic-item.active { background: #4E8E68; color: #FFFFFF; }
.hot-topics .topics-list .topic-item.active { background: #4E8E68 !important; color: #FFFFFF !important; }
.hot-topics .topics-list .topic-item.active { background-color: #4E8E68 !important; color: #FFFFFF !important; }
.hot-topics .topics-list .topic-item:nth-child(1) { background: #E8EBEE; color: #2C3E50; }
.hot-topics .topics-list .topic-item:nth-child(2) { background: #E8EBEE; color: #2C3E50; }
.hot-topics .topics-list .topic-item:nth-child(3) { background: #E8EBEE; color: #2C3E50; }

.topic-item:hover { background-color: #4E8E68; color: #FFFFFF; }

/* 响应式设计 */
@media (max-width: 1200px) {
  .community-page { padding-left: 24px; padding-right: 24px; }
}

@media (max-width: 992px) {
  .community-page { padding-left: 15px; padding-right: 15px; }
}

@media (max-width: 768px) {
  .community-page { padding: 15px; }
  .app-main { position: static; flex-direction: column; gap: 16px; min-height: auto; }
  .sidebar-left { position: static; max-height: none; overflow: visible; width: 100%; flex: 1 1 auto; }
  .feed-right { position: static; left: auto; right: auto; top: auto; max-height: none; overflow: visible; }
  .posts-masonry { flex-direction: column; }
  .posts-masonry-column { width: 100%; }
  .post-card { padding: 15px; }
  .image-grid.multi-image { grid-template-columns: repeat(2, 1fr); }
  .post-actions { flex-wrap: wrap; }
  .action-btn { flex: 1; justify-content: center; }
}

@media (max-width: 480px) {
  .community-page { padding: 10px; }
  .user-avatar { width: 40px; height: 40px; }
  .username { font-size: 1rem; }
  .post-content { font-size: 0.95rem; }
  .image-grid.multi-image { grid-template-columns: 1fr; }
}

/* 添加删除评论按钮样式 */
/* 删除底部重复样式定义 */

/* 提示信息样式 */
.message-toast {
  position: fixed;
  top: 60px;
  left: 50%;
  transform: translateX(-50%);
  padding: 12px 24px;
  border-radius: 8px;
  color: white;
  font-weight: 500;
  z-index: 1000;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  animation: slideDown 0.3s ease;
}

.message-toast.success {
  background-color: #42b983;
}

.message-toast.error {
  background-color: #e74c3c;
}

@keyframes slideDown {
  from {
    opacity: 0;
    transform: translate(-50%, -20px);
  }
  to {
    opacity: 1;
    transform: translate(-50%, 0);
  }
}
</style>
<style scoped>
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.6);
  backdrop-filter: blur(5px);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}

.modal-card {
  width: min(600px, 95vw);
  min-width: 480px;
  max-height: 80vh;
  background: #fff;
  border-radius: 16px;
  box-shadow: 0 12px 40px rgba(0,0,0,0.2);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  animation: cardIn 0.28s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: transform, opacity;
}

.modal-header {
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 12px;
  border-bottom: 1px solid #eee;
  background: #fff;
  position: sticky;
  top: 0;
  z-index: 2;
}

.modal-title { margin: 0; font-size: 16px; font-weight: 600; color: #2C3E50; }

.modal-close {
  width: 32px;
  height: 32px;
  border: none;
  border-radius: 8px;
  background: #f5f5f5;
  color: #333;
  cursor: pointer;
}

.modal-body {
  overflow: auto;
  padding: 12px 12px 0 12px;
}

.modal-fade-enter-active { animation: overlayIn 0.22s cubic-bezier(0.22, 1, 0.36, 1); }
.modal-fade-leave-active { animation: overlayOut 0.18s cubic-bezier(0.4, 0, 1, 1); }

@keyframes overlayIn { from { opacity: 0 } to { opacity: 1 } }
@keyframes overlayOut { from { opacity: 1 } to { opacity: 0 } }
@keyframes cardIn { from { transform: translateY(6px) scale(0.96); opacity: 0 } to { transform: translateY(0) scale(1); opacity: 1 } }

@media (max-width: 600px) {
  .modal-card { width: 100vw; min-width: 100vw; max-height: 100vh; border-radius: 0; }
}
</style>
<style scoped>
.detail-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.7);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1001;
}
.detail-close-floating {
  position: fixed;
  top: 120px;
  left: 24px;
  padding: 8px 12px;
  border: 1px solid #e0e0e0;
  border-radius: 10px;
  background: rgba(255,255,255,0.9);
  color: #333;
  font-size: 14px;
  cursor: pointer;
  box-shadow: 0 8px 24px rgba(0,0,0,0.2);
  z-index: 1002;
}
.detail-modal-overlay { position: fixed }
@media (max-width: 768px) { .detail-close-floating { top: 96px; left: 16px } }
.detail-close-floating:hover { background: rgba(255,255,255,0.95) }
</style>
